#ifndef __REDIS_MGR_H__
#define __REDIS_MGR_H__

#include <memory>
#include <string>
#include <vector>
#include <optional>

#include "RedisConPool.h" 

#include <hiredis/hiredis.h>

//封装 Redis 接口
class RedisMgr
{
public:
    struct ReplyDeleter 
    {
        void operator()(redisReply* r) const noexcept 
        {
            if (r) freeReplyObject(r);
        }
    };
    using ReplyPtr = std::unique_ptr<redisReply, ReplyDeleter>;

    RedisMgr() = delete;

    static std::optional<std::string> Get(RedisConPool::ConnectionHandle& conn, const std::string& key);
    static bool Set(RedisConPool::ConnectionHandle& conn, const std::string& key, const std::string& value);

    static bool LPush(RedisConPool::ConnectionHandle& conn, const std::string& key, const std::string& value);
    static std::optional<std::string> LPop(RedisConPool::ConnectionHandle& conn, const std::string& key);

    static bool RPush(RedisConPool::ConnectionHandle& conn, const std::string& key, const std::string& value);
    static std::optional<std::string> RPop(RedisConPool::ConnectionHandle& conn, const std::string& key);

    static bool LRange(RedisConPool::ConnectionHandle& conn, const std::string& key, int start, int end, std::vector<std::string>& result);

    static bool HSet(RedisConPool::ConnectionHandle& conn, const std::string& key, const std::string& hkey, const std::string& value);
    static std::optional<std::string> HGet(RedisConPool::ConnectionHandle& conn, const std::string& key, const std::string& hkey);
    static bool HDel(RedisConPool::ConnectionHandle& conn, const std::string& key, const std::string& hkey);

    static bool Del(RedisConPool::ConnectionHandle& conn, const std::string& key);
    static bool ExistsKey(RedisConPool::ConnectionHandle& conn, const std::string& key);

private:
    template<typename... Args>
    static ReplyPtr exec(redisContext* ctx, const char* fmt, Args... args) 
    {
        return ReplyPtr((redisReply*)redisCommand(ctx, fmt, args...));
    }
};

#endif // !__REDIS_MGR_H__